import { CurrentUser, RealIp } from '@/decorators';
import { AuthRealNameDto } from '@/dtos';
import { halt, ok, getBirth } from '@/utils';
import { Body, Controller, Logger, Post } from '@nestjs/common';
import { Throttle, seconds } from '@nestjs/throttler';
import { BaseController } from './base.controller';
import { UserService } from '@/services/user.service';
import dayjs from 'dayjs';
import { ZrwinfoService } from '@/core/zrwinfo.service';
import { TencentService } from '@/core/tencent.service';

@Controller('auth')
export class AuthController extends BaseController {
  constructor(
    private readonly zrwinfoService: ZrwinfoService,
    private readonly userService: UserService,
    private readonly tencentService: TencentService,
  ) {
    super();
  }

  @Post('realname')
  @Throttle({
    short: {
      ttl: seconds(3),
      limit: 1,
    },
  })
  async realname(
    @Body() dto: AuthRealNameDto,
    @CurrentUser('id') id: number,
    @RealIp() ip: string,
  ) {
    const result = await this.tencentService.describeCaptchaResult({
      UserIp: ip,
      Randstr: dto.randstr,
      Ticket: dto.ticket,
    });
    if (result?.CaptchaCode !== 1) {
      return halt(result?.CaptchaMsg ?? '验证失败');
    }

    return await this.redlock.using(
      [`auth:realname:${id}`],
      10000,
      {},
      async () => {
        const birth = getBirth(dto.idCard);
        if (dayjs().diff(dayjs(birth), 'year') < 18) {
          return halt('年龄必须大于18周岁');
        }
        if (dayjs().diff(dayjs(birth), 'year') > 65) {
          return halt('年龄必须小于65周岁');
        }
        const user = await this.userService.findOne({ id });
        if (!!user.isReal) {
          return halt('请勿重复认证');
        }

        const count = await this.prisma.user.count({
          where: {
            idCard: dto.idCard,
            isReal: true,
          },
        });
        if (count >= 5) {
          return halt('每个身份证号最多实名5次');
        }

        const res = await this.zrwinfoService.simpleTwoElements(
          dto.realname,
          dto.idCard,
        );

        await this.log.info(
          `实名认证: ${user.mobile} - ${dto.realname} - ${dto.idCard}`,
          res,
        );

        if (res.ret != 0) {
          return halt(res.msg);
        }
        if (res.data.res != 1) {
          return halt('认证失败, 请检查注册手机号, 是否与当前认证身份信息一致');
        }

        await this.userService.update({
          where: {
            id: user.id,
          },
          data: {
            realname: dto.realname,
            idCard: dto.idCard,
            isReal: true,
            authAt: new Date(),
          },
        });

        return ok(true);
      },
    );
  }
}
